package pe.com.cotelasa.scp.dominio.modelo;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import pe.com.cotelasa.common.servicios.IServicioCorreo;
import pe.com.cotelasa.scp.dominio.common.Constantes;
import pe.com.cotelasa.scp.dominio.excepcion.ModelExcepcion;
import pe.com.cotelasa.scp.dominio.excepcion.ServiceException;
import pe.com.cotelasa.scp.dominio.service.IServicioBanco;
import pe.com.cotelasa.scp.dominio.service.IServicioCuentaBancaria;
import pe.com.cotelasa.scp.dominio.service.IServicioMovimientoCuentaBancaria;
import pe.com.cotelasa.scp.dominio.service.IServicioParametro;
import pe.com.cotelasa.scp.dominio.service.IServicioParametroDetalle;
import pe.com.cotelasa.scp.dominio.service.IServicioTipoMoneda;
import pe.com.cotelasa.scp.entidad.Banco;
import pe.com.cotelasa.scp.entidad.CuentaBancaria;
import pe.com.cotelasa.scp.entidad.MovimientoCuentaBancaria;
import pe.com.cotelasa.scp.entidad.ParametroDetalle;
import pe.com.cotelasa.scp.entidad.TipoMoneda;
import pe.com.cotelasa.seguridad.dominio.servicio.IServicioEnviarCorreo;

@Component("MovCtaBancariaModel")
public class MovCtaBancariaModelImpl implements MovCtaBancariaModel {

    @Autowired
    private IServicioMovimientoCuentaBancaria servicioMovimientoCuentaBancaria;
    @Autowired
    private IServicioBanco servicioBanco;
    @Autowired
    private IServicioTipoMoneda servicioTipoMoneda;
    @Autowired
    private IServicioParametroDetalle servicioParametroDetalle;
    @Autowired
    private IServicioParametro servicioParametro;
    @Autowired
    private IServicioCuentaBancaria servicioCuentaBancaria;
    @Autowired
    private IServicioEnviarCorreo servicioCorreo;

    @Override
    public void actualizarMovimientoCuentaBancaria(MovimientoCuentaBancaria beanMovimientoCuentaBancaria) throws ModelExcepcion {
        try{
            CuentaBancaria cuenta = servicioCuentaBancaria.conseguirCuentaBancariaPorId(beanMovimientoCuentaBancaria.getIdCuentaBancaria().getId());
            beanMovimientoCuentaBancaria.setNumCuentaBancaria(cuenta.getNumeroCuenta());
            servicioMovimientoCuentaBancaria.actualizarMovCtaBancaria(beanMovimientoCuentaBancaria);
            if(beanMovimientoCuentaBancaria.getTipoMovimiento().equals(Constantes.TipoMovimiento.ENTRADA)){
                cuenta.setMontoActual(
                        cuenta.getMontoActual().add(beanMovimientoCuentaBancaria.getMonto()));
            }else{
                cuenta.setMontoActual(
                        cuenta.getMontoActual().subtract(beanMovimientoCuentaBancaria.getMonto()));
            }
            servicioCuentaBancaria.actualizarCuentaBancaria(cuenta);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public void eliminarMovimientoCuentaBancaria(MovimientoCuentaBancaria beanMovimientoCuentaBancaria) throws ModelExcepcion {
        try{
            /*CuentaBancaria cuenta = servicioCuentaBancaria.conseguirCuentaBancariaPorId(beanMovimientoCuentaBancaria.getIdCuentaBancaria().getId());
            beanMovimientoCuentaBancaria.setNumCuentaBancaria(cuenta.getNumeroCuenta());*/
            servicioMovimientoCuentaBancaria.actualizarMovCtaBancaria(beanMovimientoCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }
    
    @Override
    public void actualizarMovimientoCuentaBancariaSinMontos(MovimientoCuentaBancaria beanMovimientoCuentaBancaria) throws ModelExcepcion {
        try{
            servicioMovimientoCuentaBancaria.actualizarMovCtaBancaria(beanMovimientoCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public void guardarMovimientoCuentaBancaria(MovimientoCuentaBancaria beanMovimientoCuentaBancaria) throws ModelExcepcion {
        try {
            CuentaBancaria cuenta = servicioCuentaBancaria.conseguirCuentaBancariaPorId(beanMovimientoCuentaBancaria.getIdCuentaBancaria().getId());
            beanMovimientoCuentaBancaria.setNumCuentaBancaria(cuenta.getNumeroCuenta());
            servicioMovimientoCuentaBancaria.guardar(beanMovimientoCuentaBancaria);
            
            System.out.println("monto cuenta bancaria: "+cuenta.getMontoActual());
            System.out.println("monto movimiento: "+beanMovimientoCuentaBancaria.getMonto());
            if(beanMovimientoCuentaBancaria.getTipoMovimiento().equals(Constantes.TipoMovimiento.ENTRADA)){
                cuenta.setMontoActual(
                        cuenta.getMontoActual().add(beanMovimientoCuentaBancaria.getMonto()));
            }else{
                cuenta.setMontoActual(
                        cuenta.getMontoActual().subtract(beanMovimientoCuentaBancaria.getMonto()));
            }
            servicioCuentaBancaria.actualizarCuentaBancaria(cuenta);
            //recalcularMontoCuentaBancaria(beanMovimientoCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public void guardarMovimientoCuentaTransferida(MovimientoCuentaBancaria beanMovimientoCuentaBancaria, CuentaBancaria cuenta) throws ModelExcepcion {
        MovimientoCuentaBancaria movCuenta = new MovimientoCuentaBancaria();
        beanMovimientoCuentaBancaria.setEstadoMovimiento(MovimientoCuentaBancaria.ESTADO_MOV_CUENTA_BANCARIA.CERRADO.getValor());
        movCuenta.setEstadoMovimiento(MovimientoCuentaBancaria.ESTADO_MOV_CUENTA_BANCARIA.CERRADO.getValor());
        movCuenta.setFecCreacion(new Date());
        movCuenta.setUsrCreacion(beanMovimientoCuentaBancaria.getUsrCreacion());
        movCuenta.setFechaMovimiento(beanMovimientoCuentaBancaria.getFechaMovimiento());
        movCuenta.setFechaCierre(beanMovimientoCuentaBancaria.getFechaMovimiento());
        movCuenta.setFormaMovimiento(beanMovimientoCuentaBancaria.getFormaMovimiento());
        movCuenta.setIdCuentaBancaria(cuenta);
        movCuenta.setMonto(beanMovimientoCuentaBancaria.getMonto());
        movCuenta.setMotivo(beanMovimientoCuentaBancaria.getMotivo());
        movCuenta.setDescripcion(beanMovimientoCuentaBancaria.getMotivo());
        movCuenta.setNumCuentaBancaria(cuenta.getNumeroCuenta());
        //movCuenta.setNumFormaMovimiento(cuenta.getNumeroCuentaInterbancaria());
        movCuenta.setSaldo(BigDecimal.ZERO);
        movCuenta.setTipoMovimiento(Constantes.TipoMovimiento.ENTRADA);
        
        if(beanMovimientoCuentaBancaria.getTipoCambio() != null){
            if(beanMovimientoCuentaBancaria.getIdCuentaBancaria().getIdTipoMoneda().getId() == Constantes.TipoMoneda.DOLARES){
                movCuenta.setMonto(beanMovimientoCuentaBancaria.getTipoCambio().multiply(beanMovimientoCuentaBancaria.getMonto()));
            }else{
                movCuenta.setMonto(beanMovimientoCuentaBancaria.getMonto().divide(beanMovimientoCuentaBancaria.getTipoCambio(), MathContext.DECIMAL32));
            }
        }else{
            movCuenta.setMonto(beanMovimientoCuentaBancaria.getMonto());
        }

        guardarMovimientoCuentaBancaria(movCuenta);
        /*try {
            servicioMovimientoCuentaBancaria.guardar(beanMovimientoCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }*/
    }
    
    /*@Override
    public void recalcularMontoCuentaBancaria(MovimientoCuentaBancaria beanMovimientoCuentaBancaria) throws ModelExcepcion {
        try {
            servicioCuentaBancaria.
            
            //servicioCuentaBancaria.actualizarCuentaBancaria(beanMovimientoCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }*/
    
    @Override
    public List<MovimientoCuentaBancaria> obtenerListaMovimientoCuentaBancaria(
            MovimientoCuentaBancaria beanMovimientoCuentaBancaria, Date fechaInicio, Date fechaFinal) throws ModelExcepcion {
        try {
            return servicioMovimientoCuentaBancaria.listarMovimientoCuentaBancaria(beanMovimientoCuentaBancaria, fechaInicio, fechaFinal);
        } catch (ServiceException ex) {
            throw new ModelExcepcion(ex);
        }
    }

    @Override
    public List<Banco> obtenerListaBancosActivos() throws ModelExcepcion {
        try {
            return new ArrayList<Banco>(servicioBanco.listarBancosActivos());
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<TipoMoneda> obtenerListaMonedaActivos() throws ModelExcepcion {
        try {
            return new ArrayList<TipoMoneda>(servicioTipoMoneda.listarTipoMonedasActivos());
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<ParametroDetalle> obtenerListaTipoMovimiento()
            throws ModelExcepcion {
        try {
            return new ArrayList<ParametroDetalle>(servicioParametro.listarTipoMovimiento());
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<ParametroDetalle> obtenerListaFormaMovimiento()
            throws ModelExcepcion {
        try {
            return new ArrayList<ParametroDetalle>(servicioParametro.listarTipoPago(Constantes.FormaPago.CONTADO));
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<CuentaBancaria> obtenerListaCuentaBancaria(Integer idEmpresa)
            throws ModelExcepcion {
        try {
            return new ArrayList<CuentaBancaria>(servicioCuentaBancaria.listarCuentaBancariasPorEmpresa(idEmpresa));
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<CuentaBancaria> obtenerListaCuentaBancariasActivas()
            throws ModelExcepcion {
        try {
            return new ArrayList<CuentaBancaria>(servicioCuentaBancaria.listarCuentaBancariasActivas());
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public void enviarCorreoError(Throwable e, String mensajeError) {
        try {
            servicioCorreo.enviarCorreoError(mensajeError, e);
        } catch (ServiceException e1) {
        }
    }

    @Override
    public MovimientoCuentaBancaria obtenerMovimientoCuentaBancaria(Integer id)
            throws ModelExcepcion {
        try {
            return servicioMovimientoCuentaBancaria.conseguirMovimientoPorId(id);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public CuentaBancaria obtenerCuentaBancaria(Integer idCuentaBancaria)
            throws ModelExcepcion {
        try {
            return servicioCuentaBancaria.conseguirCuentaBancariaPorId(idCuentaBancaria);
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public List<CuentaBancaria> obtenerListaCuentaBancariaConsulta(Integer idEmpresa, Integer idCuentaBancaria) throws ModelExcepcion {
        List<CuentaBancaria> lista = new ArrayList<CuentaBancaria>();
        try {
            if(idCuentaBancaria == -1){
                lista = obtenerListaCuentaBancaria(idEmpresa);
            }else{
                lista.add(servicioCuentaBancaria.conseguirCuentaBancariaPorId(idCuentaBancaria));
            }
            
            return lista;
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }

    @Override
    public void actualizarMontoCuenta(Integer idMovCuentaBancaria) throws ModelExcepcion {
        try {
            MovimientoCuentaBancaria mov = obtenerMovimientoCuentaBancaria(idMovCuentaBancaria);
            if(mov.getTipoMovimiento().equals(Constantes.TipoMovimiento.ENTRADA)){
                mov.getIdCuentaBancaria().setMontoActual(
                        mov.getIdCuentaBancaria().getMontoActual().subtract(mov.getMonto()));
            }else{
                mov.getIdCuentaBancaria().setMontoActual(
                        mov.getIdCuentaBancaria().getMontoActual().add(mov.getMonto()));
            }
            System.out.println("monto final: "+mov.getIdCuentaBancaria().getMontoActual());
            servicioCuentaBancaria.actualizarCuentaBancaria(mov.getIdCuentaBancaria());
        } catch (ServiceException e) {
            throw new ModelExcepcion(e);
        }
    }
}
